home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 130_01 / long.c < prev    next >
Text File  |  1985-03-09  |  7KB  |  287 lines

  1. /*                LONG INTEGER PACKAGE
  2.  
  3.       The functions below, together with the Z-80 assembly
  4.     language coded routine li, constitute a package to
  5.     provide long integer capability to BDS C via function
  6.     calls similar to those provided by Bob Mathias'
  7.     floating point package.
  8.  
  9.       Note that, while the functions below are portable,
  10.     the basic workhorse function in the backage, li, will
  11.     only run on a Z-80 processor.  Further, li assumes that
  12.     the BDS C version 1.4x stack conventions are being used.
  13.  
  14.       The Long Integer Package and the function li were
  15.     programmed by Paul J. Gans, Department of Chemistry,
  16.     New York University, New York, NY  10003.  Phone
  17.     (212) 598-2515 9 am to 5 pm.
  18.  
  19.       Please let me know about bugs, problems, improvements,
  20.     or what you will.  That's the only way things will
  21.     get better.
  22.  
  23.       BDS C is copyright 1980 by Leor Zolman.
  24.  
  25.       Version record:
  26.  
  27.     Version 1.0    March 6, 1981        Original version.
  28.  
  29.     ver. 1.0a    9/12/82    by SP    ltou() and utol() added,
  30.                     bugs in ltoa(), ltoi(), fixed
  31.                     
  32.  
  33.     ver  1.1    who's gonna rewrite li() (in longcode.mac) in
  34.             casm for the 8080?
  35.  
  36.       The Long Integer Package and the function li are
  37.     copyright (c) 1981 by Paul J. Gans.
  38.  
  39.  
  40. */
  41.  
  42. #define   ADD     0
  43. #define   SUB     1
  44. #define   MUL     2
  45. #define   DIV     3
  46. #define   MOD     4
  47.  
  48. /*   ladd adds the addend and augend to produce a 32 bit
  49.    signed result in sum.  A pointer to sum is returned.  */
  50.  
  51. char *ladd(sum,addend,augend)
  52. char sum[], addend[], augend[];
  53. {
  54.     char *li();
  55.  
  56.     return (li(ADD,sum,addend,augend));
  57. }
  58.  
  59. /*   lsub subtracts subtrahend from minuend and places the
  60.    32 bit signed difference in difference.  A pointer to
  61.    difference is returned.                              */
  62.  
  63. char *lsub(difference,minuend,subtrahend)
  64. char difference[], minuend[], subtrahend[];
  65. {
  66.     char *li();
  67.  
  68.     return (li(SUB,difference,minuend,subtrahend));
  69. }
  70.  
  71. /*   lmul multiplies plier and plicand together and places
  72.    the signed low order 32 bit product in product.  A
  73.    pointer to product is returned.                      */
  74.  
  75. char *lmul(product,plier,plicand)
  76. char product[], plier[], plicand[];
  77. {
  78.     char *li();
  79.  
  80.     return (li(MUL,product,plier,plicand));
  81. }
  82.  
  83. /*   ldiv divides dividend by divisor and places the signed
  84.    low order 32 bits of the quotient in quotient.  A
  85.    pointer to quotient is returned.                   */
  86.  
  87. char *ldiv(quotient,dividend,divisor)
  88. char quotient[], dividend[], divisor[];
  89. {
  90.     char *li();
  91.  
  92.     return (li(DIV,quotient,dividend,divisor));
  93. }
  94.  
  95. /*   lmod places the 31 bit positive remainder resulting
  96.    from the division of dividend by divisor into residue.
  97.    A pointer to residue is returned.                   */
  98.  
  99. char *lmod(residue,dividend,divisor)
  100. char residue[], dividend[], divisor[];
  101. {
  102.     char *li();
  103.  
  104.     return (li(MOD,residue,dividend,divisor));
  105. }
  106.  
  107. /*   lneg places the 32 bit signed negative of orignum in
  108.    negnum and returns a pointer to it.                  */
  109.  
  110. char *lneg(negnum,orignum)
  111. char negnum[], orignum[];
  112. {
  113.     char *li(), work[4], i;
  114.  
  115.     for (i=0; i<4; ++i) work[i]=0;
  116.     return (li(SUB,negnum,work,orignum));
  117. }
  118.  
  119. /*   itol converts an integer to long form.  A pointer
  120.    to the longform is returned.                       */
  121.  
  122. char *itol(longform,i)
  123. char longform[];
  124. int i;
  125. {
  126.     longform[3]=longform[2]=0;
  127.     if (i<0) longform[3]=longform[2]=0xff;
  128.     longform[1]=i>>8;
  129.     longform[0]=i&0xff;
  130.     return longform;
  131. }
  132.  
  133. /*   ltoi returns a properly signed integer containing the
  134.    low order 15 bits of precision of the long integer
  135.     longint.  The value of this integer is placed in i and
  136.    is returned by this function.                         */
  137.  
  138. /* note, bug here, value isn't placed in 'i' of calling function,
  139.     fix by passing ADDRESS of 'i'.  also, left shifting a char
  140.     8 times empties it, not the intended action.  substituted 
  141.     appropriate code.  9/82 SP
  142. */
  143.  
  144. ltoi(i,longint)
  145. int *i;                /* i is a pointer to int */
  146. char *longint;
  147. {
  148.     char work[4];
  149.  
  150.     movmem(longint, work, 4);
  151.     if (work[3] > 127) lneg(work, work);    /* convert from 2s compliment? */
  152.     *i = ((work[1] & 0x7f) * 256) + work[0];
  153.     if (longint[3] > 127) *i = -(*i);
  154.     return *i;
  155. }
  156.  
  157. /*   atol converts the ASCII string s to a long integer
  158.    placed in longint and returns a pointer to longint.
  159.    Acceptable format for atol is:  any amount of white
  160.    space followed by an optional sign followed by a string
  161.    of decimal digits.  The first non-decimal digit stops
  162.    the scan.  The method used is an adaptation of that
  163.    presented in Kernighan and Ritchie.                */
  164.  
  165. char *atol(longint,s)
  166. char longint[], s[];
  167. {
  168.     char work[4], ten[4];
  169.     int i, j, n, sign;
  170.  
  171.     /* form a constant.. */
  172.  
  173.     ten[0]=0x0a; ten[1]=ten[2]=ten[3]=0;
  174.     /*   first skip white space... */
  175.  
  176.     for (i=0; s[i]==' ' || s[i]=='\n' || s[i]=='\t'; i++);
  177.  
  178.     /*   now get the sign... */
  179.  
  180.     sign=1;
  181.     if (s[i]=='+' || s[i]=='-')
  182.         sign=(s[i++]=='+') ? 1 : -1;
  183.  
  184.     /*   and convert the string straightforwardly... */
  185.  
  186.     for (j=0; j<4; ++j) longint[j]=0;
  187.     while (s[i]>='0' && s[i]<='9') {
  188.         for (j=0; j<4; ++j) work[j]=0;
  189.         work[0]=s[i++]-'0';
  190.         lmul(longint,ten,longint);
  191.         ladd(longint,longint,work);
  192.     }
  193.  
  194.     /*   not forgetting the original sign... */
  195.  
  196.     if (sign==-1) lneg(longint,longint);
  197.     return longint;
  198. }
  199.  
  200. /*   ltoa converts the long integer longint to an ASCII
  201.    string which is placed in s.  If longint is negative a
  202.    minus sign is prefixes the string.  The algorithm used
  203.    is an adaptation of itoa presented in Kernighan and
  204.    Ritchie.                                          */
  205.  
  206. /* note, this had a bug in that it destroyed the contents of
  207.     longint 9/82  SP */
  208.  
  209. ltoa(s,longint)
  210. char *s, *longint;
  211. {
  212.     char c, work[4], work2[4], ten[4];
  213.     int i, j, k, sign;
  214.  
  215.     ten[0]=0x0a; ten[1]=ten[2]=ten[3]=0;
  216.     movmem(longint, work2, 4);                    /* save contents of longint */
  217.     sign=1;
  218.  
  219.     /*   check the sign... */
  220.  
  221.     if (longint[3]>127) {
  222.         sign=-1;
  223.         lneg(work2,work2);
  224.     }
  225.  
  226.     /*   convert, generating digits backwards in s[]... */
  227.  
  228.     i=0;
  229.     do {
  230.         lmod(work,work2,ten);
  231.         s[i++]=work[0]+'0';
  232.         ldiv(work2,work2,ten);
  233.     } while ((work2[0]|work2[1]|work2[2]|
  234.         work2[3])!=0);
  235.  
  236.     /*   postfix a minus sign if needed... */
  237.  
  238.     if (sign==-1) s[i++]='-';
  239.     s[i]='\0';
  240.  
  241.     /*   and turn the whole thing around in place. */
  242.  
  243.     k=strlen(s);
  244.     for (i=0, j=k-1; i<j; i++, j--) {
  245.         c=s[i]; s[i]=s[j]; s[j]=c;
  246.     }
  247.  
  248.     return s;
  249. }
  250.  
  251. /********************************************************
  252.  
  253.     following added for cnode use:
  254.  
  255. */
  256.  
  257. /*   utol converts an unsigned to long form.  A pointer
  258.    to the longform is returned.                       */
  259.  
  260. char *
  261. utol(longform, u)
  262. char *longform;
  263. unsigned u;
  264. {
  265.     longform[3] = longform[2] = 0;
  266.     longform[1] = u >> 8;
  267.     longform[0] = u & 0xff;
  268.     return longform;
  269. }
  270.  
  271. /*   ltou returns an unsigned integer containing the
  272.     low order 16 bits of precision of the long integer
  273.     longform.  The value of this integer is placed in u and
  274.     is returned by this function.  It assumes that long is
  275.     positive.
  276. */
  277.  
  278. ltou(u, longform)
  279. unsigned *u;
  280. char *longform;
  281. {
  282.     return (*u = (longform[1] * 256) + longform[0]);
  283. }
  284. 0]|work2[1]|work2[2]|
  285.         work2[3])!=0);
  286.  
  287.     /*   postfix a